/**
 * File: FlavorFactory.java
 * Author: Eliana Feasley and Mark pallone
 * Emails: elf4@umbc.edu , markpa1@umbc.edu
 * Date: Jun 19, 2011
 * 
 * Description: Flavor option and Flavor generator.
 */
package data;

import java.util.ArrayList;
import model.*;

/**
 * @author mark                                WANT TO BUY DATABASE PLZ
 *
 */
public class FlavorFactory { // FLAVA FLAV FACTORIZZLE
	
	public static final String[] FLAVOR_CATEGORIES = {"soft serve ice cream",
		"scooped ice cream",
		"premium sundae",
		"classic sundae",
		"soda",
		"shake",
		"coffee drink",
		"fruit drink",
		"fruit smoothie",
		"ice cream float",
		"hash browns",
		"sandwich",
		"doughnut",
		"munchkins",
		"bagel",
		"muffin"
	};
	
	// indices into FLAVOR_CATEGORIES
	public static final int SOFT_SERVE = 0;
	public static final int SCOOPED = 1;
	public static final int PREMIUM_SUNDAE = 2;
	public static final int CLASSIC_SUNDAE = 3;
	public static final int SODA = 4;
	public static final int SHAKE = 5;
	public static final int COFFEE_DRINK = 6;
	public static final int FRUIT_DRINK = 7;
	public static final int FRUIT_SMOOTHIE = 8;
	public static final int ICE_CREAM_SODA = 9;
	public static final int HASH_BROWNS = 10;
	public static final int SANDWICH = 11;
	public static final int DOUGHNUT = 12;
	public static final int MUNCHKINS = 13;
	public static final int BAGEL = 14;
	public static final int MUFFIN = 15;
	
	public static final String[] SOFT_SERVE_FLAVORS = {"vanilla", "oreo parfait", "heath", "reese's peanut butter cup", "chocolate chip cookie dough"};
	public static final String[] SCOOPED_FLAVORS = {"vanilla", "mint chocolate chip", "chocolate", "very berry strawberry", "jamoca"};
	public static final String[] PREMIUM_SUNDAE_FLAVORS = {"reese's peanut butter cup", "chocolate chip cookie dough", "OREO layered"};
	public static final String[] CLASSIC_SUNDAE_FLAVORS = {"banana royale", "brownie", "classic banana split"};
	public static final String[] SODA_FLAVORS = {"coke", "root beer"};
	public static final String[] SHAKE_FLAVORS = {"vanilla", "chocolate"};
	public static final String[] COFFEE_DRINK_FLAVORS = {"oreo 'n cookies", "cappuccino blast", "caramel cappuccino blast"};
	public static final String[] FRUIT_DRINK_FLAVORS = {"strawberry fruit cream", "mango fruit cream"};
	public static final String[] FRUIT_SMOOTHIE_FLAVORS = {"strawberry citrus", "wild mango"};
	public static final String[] HASH_BROWN_FLAVORS = {"normal", "double fried"};
	public static final String[] SANDWICH_FLAVORS = {"tuna", "ham", "egg", "sausage"};
	public static final String[] DOUGHNUT_FLAVORS = {"chocolate", "powdered", "glazed"};
	public static final String[] BAGEL_FLAVORS = {"plain", "everything", "whole wheat"};
	public static final String[] MUFFIN_FLAVORS = {"blueberry", "chocolate", "pumpkin"};
	public static final String[] COFFEE_FLAVORS = {"black", "sugar", "cream", "sugar and cream"};
	
	// prices
	public static final double SOFT_SERVE_PRICE = 3;
	public static final double SCOOPED_PRICE = 4;
	public static final double PREMIUM_SUNDAE_PRICE = 5;
	public static final double CLASSIC_SUNDAE_PRICE = 5;
	
	public static final double SMALL_SODA_PRICE = 1;
	public static final double MEDIUM_SODA_PRICE = 1.25;
	public static final double LARGE_SODA_PRICE = 1.50;
	
	public static final double SMALL_SHAKE_PRICE = 2;
	public static final double MEDIUM_SHAKE_PRICE = 2.25;
	public static final double LARGE_SHAKE_PRICE = 2.50;
	
	public static final double SMALL_COFFEE_DRINK = 1;
	public static final double MEDIUM_COFFEE_DRINK = 1.25;
	public static final double LARGE_COFFEE_DRINK = 1.50;
	
	public static final double SMALL_FRUIT_DRINK_COST = 2.00;
	public static final double MEDIUM_FRUIT_DRINK_COST = 2.25;
	public static final double LARGE_FRUIT_DRINK_COST = 2.50;
	
	public static final double SMALL_FRUIT_SMOOTHIE_COST = 3;
	public static final double MEDIUM_FRUIT_SMOOTHIE_COST = 3.25;
	public static final double LARGE_FRUIT_SMOOTHIE_COST = 3.5;
	
	public static final double SMALL_ICECREAM_SODA_COST = 2;
	public static final double MEDIUM_ICECREAM_SODA_COST = 2.25;
	public static final double LARGE_ICECREAM_SODA_COST = 2.5;
	
	public static final double HASH_BROWN_COST = .89;
	
	public static final double SANDWICH_INGREDIENT_COST = 1.49;
	
	public static final double DOUGHNUT_COST = .89;
	
	public static final double MUNCHKIN_COST = .49;
	
	public static final double BAGEL_COST = 1.29;
	
	public static final double MUFFIN_COST = 1.39;
	
	// weights (in ounces) 
	public static final double SOFT_SERVE_WEIGHT = 5;
	public static final double SCOOPED_WEIGHT = 2.5;
	public static final double PREMIUM_SUNDAE_WEIGHT = 5;
	public static final double CLASSIC_SUNDAE_WEIGHT = 5;
	public static final double SODA_WEIGHT = 8;
	public static final double SHAKE_WEIGHT = 8;
	public static final double COFFEE_WEIGHT = 8;
	public static final double FRUIT_DRINK_WEIGHT = 8;
	public static final double FRUIT_SMOOTHIE_WEIGHT = 8;
	public static final double SIZE_DIFFERENCE = 4; // difference between medium and large, difference between small and medium
	public static final double HASH_BROWN_WEIGHT = 8;
	public static final double SANDWICH_WEIGHT = 12;
	public static final double TUNA_WEIGHT = 6;
	public static final double EGG_WEIGHT = 6;
	public static final double SAUSAGE_WEIGHT = 6;
    public static final double DOUGHNUT_WEIGHT = 5;
    public static final double MUNCHKIN_WEIGHT = 2;
    public static final double BAGEL_WEIGHT = 5;
    public static final double MUFFIN_WEIGHT = 5;

	/*
	public ArrayList<String> getFlavorOptions(Treat treat) throws Exception {
		return getFlavorOptions(treat.getTreatType());
	}*/ //TODO remove this
	
	
	/**
	 * 
	 * getFlavorOptions - get the flavor options given the type of treat
	 * Preconditions: treatType must be in FLAVOR_CATEGORIES
	 * Postconditions: a list of available treat options is returned
	 * @param treat the type of treat from FLAVOR_CATEGORIES
	 * @return a list of flavor options for the given type of treat
	 * @throws Exception treatType must be in FLAVOR_CATEGORIES
	 */
	public ArrayList<String> getFlavorOptions(Treat treat) throws Exception { // returns "coke", "root beer" for if treatChoice is "soda", etc.
		ArrayList<String> options = new ArrayList<String>();
		
		if ( treat instanceof SoftServeIceCream ) {
			addAll(options, SOFT_SERVE_FLAVORS);
		} else if (treat instanceof ScoopedIceCream) {
			addAll(options, SCOOPED_FLAVORS);
		} else if (treat instanceof PremimSundae) {
			addAll(options, PREMIUM_SUNDAE_FLAVORS);
		} else if (treat instanceof ClassicSundae) {
			addAll(options, CLASSIC_SUNDAE_FLAVORS);
		} else if (treat instanceof Soda) {
			addAll(options, SODA_FLAVORS);
		} else if (treat instanceof Shake) {
			addAll(options, SHAKE_FLAVORS);
		} else if (treat instanceof CoffeeDrink) {
			addAll(options, COFFEE_DRINK_FLAVORS);
		} else if (treat instanceof FruitDrink) {
			addAll(options, FRUIT_DRINK_FLAVORS);
		} else if (treat instanceof Smoothie) {
			addAll(options, FRUIT_SMOOTHIE_FLAVORS);
		} else if (treat instanceof HashBrowns) {
			addAll(options, HASH_BROWN_FLAVORS);
		} else if (treat instanceof Sandwich) {
			addAll(options, SANDWICH_FLAVORS);
		} else if (treat instanceof Doughnut) {
			addAll(options, DOUGHNUT_FLAVORS);
		} else if (treat instanceof Munchkins) {
			addAll(options, DOUGHNUT_FLAVORS);
		} else if (treat instanceof Bagel) {
			addAll(options, BAGEL_FLAVORS);
		} else if (treat instanceof Muffin) {
			addAll(options, MUFFIN_FLAVORS);
		} else if (treat instanceof Coffee) {
			addAll(options, COFFEE_FLAVORS);
		} 
		
		else {
			throw new Exception("Unknown treat type: '" + treat + "'");
		}
		
		return options;
	}
	
	
	/**
	 * canHaveMultipleFlavors - returns true if the treat can have
	 * more than one flavor, false otherwise
	 * Preconditions: none
	 * Postconditions: returns true if the treat can have
	 * more than one flavor, false otherwise
	 * @param treat the type of treat from FLAVOR_CATEGORIES
	 * @return true if the treat can have more than one flavor, false otherwise
	 */
	public boolean canHaveMultipleFlavors(Treat t) {
		if (t instanceof IceCream || t instanceof Sandwich){
			return true;
		} else {
			return false;
		}
	}
	
	/**
	 * 
	 * addAll - add all of the elements in 'array' to 'arrayList'
	 * Preconditions: none
	 * Postconditions: all of the elements in array are added to arrayList
	 * @param arrayList the arrayList to be added to
	 * @param array the array from which to add items
	 */
	private void addAll(ArrayList<String> arrayList, String[] array) {
		for (int i = 0; i < array.length; i++) {
			arrayList.add(array[i]);
		}
	}
	
	
	/**
	 * 
	 * getFlavorCategories - get all of the potential flavor categories (this list is pulled from FLAVOR_CATEGORIES
	 * Preconditions: none
	 * Postconditions: list of flavor categories is returned
	 * @return list of flavor categories
	 */
	public ArrayList<String> getFlavorCategories() {
		ArrayList<String> categories = new ArrayList<String>();
		
		for (int i = 0; i < FLAVOR_CATEGORIES.length; i++) {
			categories.add(FLAVOR_CATEGORIES[i]);
		}
		
		return categories;
	}
	
	private double getWeight(Treat treat) {
		double weight = 0;
		
		if ( treat instanceof SoftServeIceCream ) {
			weight = SOFT_SERVE_WEIGHT;
		} else if (treat instanceof ScoopedIceCream) {
			weight = SCOOPED_WEIGHT;
		} else if (treat instanceof PremimSundae) {
			weight = PREMIUM_SUNDAE_WEIGHT;
		} else if (treat instanceof ClassicSundae) {
			weight = CLASSIC_SUNDAE_WEIGHT;
		} else if (treat instanceof Soda) {
			weight = SODA_WEIGHT;
			if (treat.getContainer().getSize().equals(ContainerFactory.CONTAINER_OPTIONS[ContainerFactory.MEDIUM])) {
				weight += SIZE_DIFFERENCE;
			} else if (treat.getContainer().getSize().equals(ContainerFactory.CONTAINER_OPTIONS[ContainerFactory.LARGE])) {
				weight += SIZE_DIFFERENCE * 2;
			}
		} else if (treat instanceof Shake) {
			weight = SHAKE_WEIGHT;
			if (treat.getContainer().getSize().equals(ContainerFactory.CONTAINER_OPTIONS[ContainerFactory.MEDIUM])) {
				weight += SIZE_DIFFERENCE;
			} else if (treat.getContainer().getSize().equals(ContainerFactory.CONTAINER_OPTIONS[ContainerFactory.LARGE])) {
				weight += SIZE_DIFFERENCE * 2;
			}
		} else if (treat instanceof CoffeeDrink || treat instanceof Coffee) {
			weight = COFFEE_WEIGHT;
			if (treat.getContainer().getSize().equals(ContainerFactory.CONTAINER_OPTIONS[ContainerFactory.MEDIUM])) {
				weight += SIZE_DIFFERENCE;
			} else if (treat.getContainer().getSize().equals(ContainerFactory.CONTAINER_OPTIONS[ContainerFactory.LARGE])) {
				weight += SIZE_DIFFERENCE * 2;
			}
		} else if (treat instanceof FruitDrink) {
			weight = FRUIT_DRINK_WEIGHT;
			if (treat.getContainer().getSize().equals(ContainerFactory.CONTAINER_OPTIONS[ContainerFactory.MEDIUM])) {
				weight += SIZE_DIFFERENCE;
			} else if (treat.getContainer().getSize().equals(ContainerFactory.CONTAINER_OPTIONS[ContainerFactory.LARGE])) {
				weight += SIZE_DIFFERENCE * 2;
			}
		} else if (treat instanceof Smoothie) {
			weight = FRUIT_SMOOTHIE_WEIGHT;
			if (treat.getContainer().getSize().equals(ContainerFactory.CONTAINER_OPTIONS[ContainerFactory.MEDIUM])) {
				weight += SIZE_DIFFERENCE;
			} else if (treat.getContainer().getSize().equals(ContainerFactory.CONTAINER_OPTIONS[ContainerFactory.LARGE])) {
				weight += SIZE_DIFFERENCE * 2;
			}
		} else if (treat instanceof Sandwich) {
			weight = SANDWICH_WEIGHT; 
		} else if (treat instanceof HashBrowns) {
			weight = HASH_BROWN_WEIGHT;
		} else if (treat instanceof Doughnut) {
			weight = DOUGHNUT_WEIGHT;
		} else if (treat instanceof Munchkins) {
			weight = MUNCHKIN_WEIGHT;
		} else if (treat instanceof Bagel) {
			weight = BAGEL_WEIGHT;
		} else if (treat instanceof Muffin) {
			weight = MUFFIN_WEIGHT;
		}
		
		else {
			System.out.println("Unknown treat type: '" + treat + "'");
		}
		
		return weight;
	}
	
	private double getCost(Treat treat, String size) {
		double cost = 0;
		
		if ( treat instanceof SoftServeIceCream ) {
			cost = SOFT_SERVE_PRICE;
		} else if (treat instanceof ScoopedIceCream) {
			cost = SCOOPED_PRICE;
		} else if (treat instanceof PremimSundae) {
			cost = PREMIUM_SUNDAE_PRICE;
		} else if (treat instanceof ClassicSundae) {
			cost = CLASSIC_SUNDAE_PRICE;
		} else if (treat instanceof Soda) {
			cost = getSodaCost(size);
		} else if (treat instanceof Shake) {
			cost = getShakeCost(size);
		} else if (treat instanceof CoffeeDrink || treat instanceof Coffee) {
			cost = getCoffeeDrinkCost(size);
		} else if (treat instanceof FruitDrink) {
			cost = getFruitDrinkCost(size);
		} else if (treat instanceof Smoothie) {
			cost = getFruitSmoothieCost(size);
		} else if (treat instanceof HashBrowns) {
			cost = HASH_BROWN_COST;
		} else if (treat instanceof Sandwich) {
			cost = getSandwichCost(treat);
		} else if (treat instanceof Doughnut) {
			cost = getDoughnutCost(treat);
		} else if (treat instanceof Munchkins) {
			cost = MUNCHKIN_COST;
		} else if (treat instanceof Bagel) {
			cost = BAGEL_COST;
		} else if (treat instanceof Muffin) {
			cost = MUFFIN_COST;
		}
		
		else {
			System.out.println("Unknown treat type: '" + treat + "'");
		}
		
		return cost;
	}
	
	private double getDoughnutCost(Treat treat) {
		return DOUGHNUT_COST;
	}


	private double getSandwichCost(Treat treat) {
		return SANDWICH_INGREDIENT_COST;
	}


	private double getFruitSmoothieCost(String size) {
		double cost = 0;
		
		if (size.equals(ContainerFactory.CONTAINER_OPTIONS[ContainerFactory.SMALL])) {
			cost = SMALL_FRUIT_SMOOTHIE_COST;
		} else if (size.equals(ContainerFactory.CONTAINER_OPTIONS[ContainerFactory.MEDIUM])) {
			cost = MEDIUM_FRUIT_SMOOTHIE_COST;
		} else if (size.equals(ContainerFactory.CONTAINER_OPTIONS[ContainerFactory.LARGE])) {
			cost = LARGE_FRUIT_SMOOTHIE_COST;
		}
		
		return cost;
	}

	private double getFruitDrinkCost(String size) {
		double cost = 0;
		
		if (size.equals(ContainerFactory.CONTAINER_OPTIONS[ContainerFactory.SMALL])) {
			cost = SMALL_FRUIT_DRINK_COST;
		} else if (size.equals(ContainerFactory.CONTAINER_OPTIONS[ContainerFactory.MEDIUM])) {
			cost = MEDIUM_FRUIT_DRINK_COST;
		} else if (size.equals(ContainerFactory.CONTAINER_OPTIONS[ContainerFactory.LARGE])) {
			cost = LARGE_FRUIT_DRINK_COST;
		}
		
		return cost;
	}

	private double getCoffeeDrinkCost(String size) {
		double cost = 0;
		
		if (size.equals(ContainerFactory.CONTAINER_OPTIONS[ContainerFactory.SMALL])) {
			cost = SMALL_COFFEE_DRINK;
		} else if (size.equals(ContainerFactory.CONTAINER_OPTIONS[ContainerFactory.MEDIUM])) {
			cost = MEDIUM_COFFEE_DRINK;
		} else if (size.equals(ContainerFactory.CONTAINER_OPTIONS[ContainerFactory.LARGE])) {
			cost = LARGE_COFFEE_DRINK;
		}
		
		return cost;
	}

	private double getShakeCost(String size) {
		double cost = 0;
		
		if (size.equals(ContainerFactory.CONTAINER_OPTIONS[ContainerFactory.SMALL])) {
			cost = SMALL_SHAKE_PRICE;
		} else if (size.equals(ContainerFactory.CONTAINER_OPTIONS[ContainerFactory.MEDIUM])) {
			cost = MEDIUM_SHAKE_PRICE;
		} else if (size.equals(ContainerFactory.CONTAINER_OPTIONS[ContainerFactory.LARGE])) {
			cost = LARGE_SHAKE_PRICE;
		}
		
		return cost;
	}

	private double getSodaCost(String size) {
		double cost = 0;
		
		if (size.equals(ContainerFactory.CONTAINER_OPTIONS[ContainerFactory.SMALL])) {
			cost = SMALL_SODA_PRICE;
		} else if (size.equals(ContainerFactory.CONTAINER_OPTIONS[ContainerFactory.MEDIUM])) {
			cost = MEDIUM_SODA_PRICE;
		} else if (size.equals(ContainerFactory.CONTAINER_OPTIONS[ContainerFactory.LARGE])) {
			cost = LARGE_SODA_PRICE;
		}
		
		return cost;
	}

	/**
	 * 
	 * getFlavor - given a flavor option, get a flavor Object. The flavor option should match one returned by getFlavorOptions()
	 * Preconditions: flavorOption must match a string returned by getFlavorOptions()
	 * Postconditions: a Flavor object is returned
	 * @param flavorOption a string from getFlavorOptions()
	 * @param size size of the flavor, to determine cost
	 * @return a Flavor object
	 */
	public Flavor getFlavor(String flavorOption, Treat treat) {
		
		String type = treat.getTreatType();
		String name = flavorOption;
		double price = getCost(treat, treat.getContainer().getSize());
		double weight = getWeight(treat);
		
		Flavor flav = new Flavor(type, name, price, weight);
		
		return flav;
	}
	
	
	
	
}
